﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using ElementumForever.Factory;
using LuaInterface;
using ElementumForever.Utility;
using ElementumForever.Editer;
using ElementumForever.Interfaces;
using ElementumForever.Enums;

namespace ElementumForever
{
    public abstract class BaseScene : BaseEntity, IScene
    {
        private List<IUpdateHandler> UpdateHandlers;
        protected PhysicalWorld world;
        public MainGame MainGame { get; private set; }
        public float GravityX { get; set; }
        public float GravityY { get; set; }
        public PhysicalWorld World { get { return world; } protected set { world = value; } }
        protected RectangleShape backGround;

        public BaseScene(MainGame game)
        {
        }

        protected virtual void Initialize(MainGame game)
        {
            MainGame = game;
            Children = new EntityList();
            Name = "untittled scene";
            Zoom = 1;
            Rotation = 0;
            Alpha = 1;
            ScaleX = ScaleY = 1;
            ObjectClass = EObjectClass.scene;
            Width = GraphicConstant.WINDOW_WIDTH;
            Height = GraphicConstant.WINDOW_HEIGHT;
            Center = new Vector2(Width / 2, Height / 2);
            Color = Color.Black;
            //SceneData _sceneData = this.Serialize();
        }

        public override void OnCreat()
        {
            base.OnCreat();
            //Color = Color.Black;
            UpdateHandlers = new List<IUpdateHandler>();
            backGround = new RectangleShape();
            backGround.Name = "backGround";
            backGround.OnCreat();
            backGround.OnAttach(this);
            backGround.LayerDepth = -100;
        }

        private void UpdateBackGround(GameTime gameTime)
        {
            backGround.OnUpdate(gameTime);
            backGround.Width = Width;
            backGround.Height = Height;
            backGround.Color = Color * Alpha;
        }

        public float Zoom { get { return ScaleX; } set { ScaleX = ScaleY = value; } }

        public Vector2 Center
        {
            get { return new Vector2(CenterX, CenterY); }
            set
            {
                CenterX = value.X; 
                CenterY = value.Y;
                X = CenterX;
                Y = CenterY;
                OriginX = Width / 2;
                OriginY = Height / 2;
            }
        }

        public GraphicsDevice GraphicsDevice
        {
            get { return MainGame.GraphicsDevice; }
        }

        public override void OnUpdate(GameTime gameTime)
        {
            foreach (IUpdateHandler updateHandler in UpdateHandlers)
                updateHandler.OnUpdate(gameTime);
            base.OnUpdate(gameTime);
            UpdateBackGround(gameTime);
        }

        public override void Dispose()
        { }

        public void RegistUpdateHandler(IUpdateHandler updateHandler)
        {
            this.UpdateHandlers.Add(updateHandler);
        }

        public bool RemoveUpdateHandler(IUpdateHandler updateHandler)
        {
            return this.UpdateHandlers.Remove(updateHandler);
        }


        public void Reset()
        {
            Zoom = 1;
            Rotation = 0;
            Center = new Vector2(GraphicConstant.WINDOW_WIDTH / 12, GraphicConstant.WINDOW_HEIGHT / 2);
        }

        public override IEntity Clone()
        {
            throw new NotImplementedException();
        }

        public bool OnHandleInput(Keys keyId, EButtonState state)
        {
            return false;
        }

        public void CreatPhysicalWorld(Vector2 gravity, bool doSleep)
        {

            this.GravityX = gravity.X;
            this.GravityY = gravity.Y;

            if (this.World == null)
            {
                this.World = new PhysicalWorld(gravity, doSleep);
                this.RegistUpdateHandler(this.World);
            }
            else
            {
                this.World.Gravity = gravity;
            }
        }

        public string SceneDataString
        {
            get
            {
                EntityInfo sceneData = this.Serialize();
                return LuaFactory.ToLuaCodeString(sceneData);
            }
        }

        public bool HasPhysics { get; set; }

        public float CenterX
        {
            get { return X; }
            set { X = value;}
        }

        public float CenterY
        {
            get { return Y; }
            set { Y = value; }
        }

        public SpriteBatch SpriteBatch
        {
            get { return MainGame.SpriteBatch; }
        }

        protected override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {}

        public override void OnDraw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            backGround.OnDraw(gameTime, spriteBatch);
            base.OnDraw(gameTime, spriteBatch);
        }

        public override EntityInfo Serialize()
        {
            return EntitySerializer.SerializeScene(this);
        }

        public override void Build(IsceneBuilder builder, LuaTable define)
        {
            builder.InitializeScene(this,define);
        }
    }
}
